<!--
 * @Description: 软终端管理
 * @Author: 0001100986/LiuShuai
 * @Date: 2021-06-10 14:26:28
 * @LastEditTime: 2021-11-11 16:28:22
 * @LastEditors: 0001100986/LiuShuai
-->
<template>
  <div class="introduce-box">
    <div v-if="!optionStatus" class="page-content">
      <table-bar :showTop="false" :columns="columns" @changeColumn="changeColumn">
        <div slot="top">
          <el-form :model="filterSearch" label-width="80px" label-position="right">
            <el-row :gutter="20">
              <el-col :xs="24" :sm="12" :lg="6">
                <!-- 用户名称 -->
                <el-form-item label="用户名称">
                  <el-input v-model.trim="filterSearch.userName" placeholder="请输入用户名称"></el-input>
                </el-form-item>
              </el-col>
              <el-col :xs="24" :sm="12" :lg="6">
                <!-- 租户选择 -->
                <el-form-item label="租户选择">
                  <el-select
                    class="order-cover-select"
                    v-model="filterSearch.dgId"
                    clearable
                    @clear="filterVmModel"
                    placeholder="请选择租户"
                    filterable
                    v-el-select-loadmore="loadmore"
                    :filter-method="filterVmModel"
                    style="width: 100%:"
                    v-adaption
                  >
                    <el-option
                      v-for="item in seloptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    ></el-option>
                  </el-select>
                </el-form-item>
              </el-col>
              <!-- 搜索 重置 -->
              <el-row :xs="24" :sm="12" :lg="6" style="float: right; margin-right: 10px;">
                <el-button type="primary" @click="search">搜索</el-button>
                <el-button @click="reset">重置</el-button>
              </el-row>
            </el-row>
          </el-form>
        </div>
        <div slot="bottom">
          <!-- 新建 -->
          <el-button size="medium" type="primary" plain @click="showDialog('add')" v-power="2">新建</el-button>
        </div>
      </table-bar>
      <div class="on-off-box">
        <el-tag type="success" effect="dark">在线 {{online}}</el-tag>
        <el-tag type="danger" effect="dark">离线 {{offline}}</el-tag>
      </div>
      <tao-table
        class="table-box"
        :data="dataList"
        :page="page"
        @changePage="changePage"
        :showPage="true"
        ref="table"
      >
        <!-- ID -->
        <el-table-column
          v-if="columns[0].show"
          align="center"
          width="100"
          label="ID"
          sortable
          prop="id"
        />
        <!-- 软终端名称 -->
        <el-table-column
          v-if="columns[1].show"
          min-width="200"
          label="软终端名称"
          show-overflow-tooltip
          prop="name"
        />
        <!-- 所属租户 -->
        <el-table-column
          v-if="columns[2].show"
          align="center"
          width="150"
          label="所属租户"
          show-overflow-tooltip
          prop="extAttrs.dgName"
        />
        <!-- 用户名称 -->
        <el-table-column
          v-if="columns[3].show"
          align="center"
          width="150"
          label="用户名称"
          show-overflow-tooltip
          prop="userName"
        />
        <!-- 序列号 -->
        <el-table-column
          v-if="columns[4].show"
          align="center"
          width="280"
          label="序列号"
          show-overflow-tooltip
          prop="deviceId"
        />
        <!-- 宿主机MAC -->
        <el-table-column
          v-if="columns[5].show"
          align="center"
          width="150"
          label="宿主机MAC"
          prop="hostId"
        />
        <!-- 状态 -->
        <el-table-column
          v-if="columns[6].show"
          align="center"
          width="100"
          sortable
          label="状态"
          prop="status"
        >
          <template slot-scope="scope">
            <!-- 已登录、未登录 -->
            <span v-if="scope.row.status === 0">
              <i class="i-login"></i>已登录
            </span>
            <span v-if="scope.row.status === 1">
              <i class="i-out"></i>未登录
            </span>
          </template>
        </el-table-column>
        <!-- DNS -->
        <el-table-column
          v-if="columns[7].show"
          align="center"
          width="150"
          label="DNS"
          prop="dnsIp"
        />
        <!-- VPN Server -->
        <el-table-column
          v-if="columns[8].show"
          align="center"
          width="150"
          label="VPN Client"
          prop="vpn"
        >
          <template
            slot-scope="scope"
          >{{ scope.row.lan ? scope.row.lan.ip : '' }}{{ scope.row.pop ? ' - ' + scope.row.pop.ip : '' }}</template>
        </el-table-column>
        <!-- IP地址 -->
        <el-table-column
          v-if="columns[9].show"
          align="center"
          width="180"
          label="WAN IP"
          prop="extAttrs.vpnClientIp"
        />
        <!-- 登录时间 -->
        <el-table-column
          v-if="columns[10].show"
          align="center"
          width="170"
          sortable
          label="登录时间"
          prop="loginInTime"
        >
          <template slot-scope="scope">{{ scope.row.loginInTime | filterTime }}</template>
        </el-table-column>
        <!-- 登出时间 -->
        <el-table-column
          v-if="columns[11].show"
          align="center"
          width="170"
          sortable
          label="登出时间"
          prop="loginOutTime"
        >
          <template slot-scope="scope">{{ scope.row.loginOutTime | filterTime }}</template>
        </el-table-column>
        <!-- 操作 -->
        <el-table-column fixed="right" label="操作" align="center" width="320px">
          <!-- 配置  删除-->
          <template slot-scope="scope">
            <el-button
              type="text"
              icon="el-icon-paperclip"
              style="color: #409eff"
              @click="showDNS(scope.row)"
              v-power="scope.row.dgId === 100000 ? 0 : 2"
            >DNS设置</el-button>
            <el-button
              type="text"
              icon="el-icon-download"
              style="color: #E6A23C"
              @click="download(scope.row)"
              v-power="scope.row.dgId === 100000 ? 0 : 2"
            >证书下载</el-button>
            <el-button
              type="text"
              icon="el-icon-setting"
              style="color: #67C23A"
              @click="options(scope.row)"
              v-power="scope.row.dgId === 100000 ? 0 : 2"
            >配置</el-button>
            <el-button
              type="text"
              style="color: #FA6962"
              icon="el-icon-delete"
              @click="handleDelete(scope)"
              v-power="scope.row.dgId === 100000 ? 0 : 2"
            >删除</el-button>
          </template>
        </el-table-column>
      </tao-table>
      <el-dialog title="DNS设置" width="300px" :close-on-click-modal="false" :visible.sync="dnsEdit">
        <el-form ref="dnsForm" :model="dnsform" label-position="right">
          <el-form-item
            prop="dnsIp"
            :rules="[{ required: true, message: '请输入DNS Server IP', trigger: 'blur'}]"
          >
            <el-input v-model="dnsform.dnsIp" />
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <!--取 消  确 定-->
          <el-button @click="dnsEdit = false">取消</el-button>
          <el-button type="primary" @click="subDNS">确认</el-button>
        </span>
      </el-dialog>
      <el-dialog
        title="VPN Server"
        width="300px"
        :close-on-click-modal="false"
        :visible.sync="vpnEdit"
      >
        <el-form ref="vpnForm" :model="vpnform" label-position="right">
          <el-form-item
            prop="pop"
            :rules="[{ required: true, message: '请选择POP', trigger: 'change'}]"
          >
            <el-select v-model="vpnform.pop" style="width:100%;">
              <el-option
                v-for="(item, index) in popls"
                :key="index"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <!--取 消  确 定-->
          <el-button @click="vpnEdit = false">取消</el-button>
          <el-button type="primary" @click="subVPN">确认</el-button>
        </span>
      </el-dialog>
      <el-dialog
        :title="dialogTitle"
        :close-on-click-modal="false"
        width="500px"
        :visible.sync="dvEdit"
      >
        <el-form
          ref="ruleForm"
          :model="form"
          :rules="rules"
          label-width="100px"
          label-position="right"
        >
          <!-- 软终端名称 -->
          <el-form-item label="软终端名称" prop="name">
            <el-input v-model="form.name" maxlength="200"></el-input>
          </el-form-item>
          <!-- 用户名 -->
          <el-form-item label="用户名" prop="userName">
            <el-input v-model="form.userName" maxlength="200"></el-input>
          </el-form-item>
          <!-- 授权码 -->
          <el-form-item label="授权码" prop="licenseKey">
            <el-input v-model="form.licenseKey" maxlength="200"></el-input>
          </el-form-item>
          <!-- 所属租户 -->
          <el-form-item label="所属租户" prop="dgId">
            <el-select v-model="form.dgId" filterable style="width:100%">
              <el-option
                v-for="item in tenantArry"
                :key="item.id"
                :value="item.id"
                :label="item.userlabel"
              ></el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <!--取 消  确 定-->
          <el-button @click="dvEdit = false">取消</el-button>
          <el-button type="primary" @click="onSubmit">确认</el-button>
        </span>
      </el-dialog>
    </div>
    <div v-if="optionStatus" class="options-content">
      <options :introduce="introduce" @handleChange="handleChange($event)" />
    </div>
  </div>
</template>

<script>
import options from '../options';
export default {
  components: {
    options
  },
  directives: {
    // 计算是否滚动到最下面
    'el-select-loadmore': {
      bind (el, binding) {
        // 获取element-ui定义好的scroll盒子
        const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
        SELECTWRAP_DOM.addEventListener('scroll', function() {
          // scrollHeight 获取元素内容高度(只读)
          // scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
          // clientHeight 读取元素的可见高度(只读)
          // 如果元素滚动到底, 下面等式返回true, 没有则返回false:
          const condition = Math.round(this.scrollHeight - this.scrollTop) <= this.clientHeight;
          if (condition) {
            binding.value();
          }
        });
      }
    }
  },
  filters: {
    // 过滤时间
    filterTime (val) {
      if (val === undefined || val === null || val === '') {
        val = '';
      } else {
        val = val.substring(0, 19);
      }
      return val;
    }
  },
  data () {
    return {
      // 分页数据
      seloptions: [],
      // 分页参数
      selPage: {
        page: 1,
        pageSize: 15,
        total: 0
      },
      // 筛选文本
      filterText: '',
      tenantArry: [],
      dvEdit: false,
      dialogTitle: '',
      // DNS 设置
      dnsEdit: false,
      dnsform: {
        dnsIp: null
      },
      // VPN Server
      popls: [],
      vpnEdit: false,
      vpnform: {
        pop: null
      },
      page: {
        page: 1,
        pageSize: 15,
        total: 0
      },
      form: {
        name: null,
        userName: null,
        licenseKey: null,
        deviceId: null,
        dgId: null
      },
      dataList: [],
      online: 0,
      offline: 0,
      filterSearch: {
        userName: null,
        dgId: null
      },
      columns: [
        { name: 'ID', show: true },
        { name: '软终端名称', show: true },
        { name: '所属租户', show: true },
        { name: '用户名称', show: true },
        { name: '序列号', show: true },
        { name: '宿主机MAC', show: true },
        { name: '状态', show: true },
        { name: 'DNS', show: true },
        { name: 'VPN Client', show: true },
        { name: 'IP地址', show: true },
        { name: '登录时间', show: true },
        { name: '登出时间', show: true }
      ],
      rules: {
        name: [{ required: true, message: '请输入软终端名称', trigger: 'blur' }],
        userName: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
        licenseKey: [{ required: true, message: '请输入授权码', trigger: 'blur' }],
        dgId: [{ required: true, message: '请选择租户', trigger: 'change' }]
      },
      introduce: {},
      optionStatus: false
    };
  },
  mounted () {
    let _this = this;
    _this.$nextTick(() => {
      _this.refresh();
      _this.getTenants();
      _this.loadmore(true);
    });
  },
  methods: {
    // 证书下载
    download (data) {
      let _this = this;
      _this.$http.downloadPost({
        url: '/api/sdwan/vpn/server/download'
      }).then(res => {
        const filename = res.headers["content-disposition"];
        const blob = new Blob([res.data]);
        let downloadElement = document.createElement("a");
        let href = window.URL.createObjectURL(blob);
        downloadElement.href = href;
        downloadElement.download = decodeURIComponent(filename.split("filename=")[1]);
        document.body.appendChild(downloadElement);
        downloadElement.click();
        document.body.removeChild(downloadElement);
        window.URL.revokeObjectURL(href);
      });
    },
    // 分页方法 详见 directives
    loadmore (firstTag) {
      let _this = this;
      // 筛选时下拉不触发分页
      if (!_this.filterText) {
        if (!firstTag) {
          _this.selPage.page++;
        }
        let params = {
          limit: _this.selPage.pageSize,
          offset: (_this.selPage.page - 1) * _this.selPage.pageSize
        };
        _this.$http.post({
          url: '/api/sdwan/tenant/getMultiDg',
          data: params
        }).then(res => {
          let { status, resultBody } = res;
          if (status === '0') {
            let { objects } = resultBody;
            let arry = [];
            for (let i = 0; i < objects.length; i++) {
              arry.push({
                label: objects[i].userlabel,
                value: objects[i].id
              });
            }
            _this.seloptions.push(...arry);
          }
        });
      }
    },
    // 筛选方法
    filterVmModel (value) {
      let _this = this;
      _this.filterText = value;
      // 筛选数据，有值时清空选项并按照关键字搜索对应结果集合
      if (value) {
        _this.seloptions = [];
        _this.$nextTick(() => {
          _this.selPage = {
            page: 1,
            pageSize: 15,
            total: 0
          };
          let params = {
            label: _this.filterText,
            limit: _this.selPage.pageSize,
            offset: (_this.selPage.page - 1) * _this.selPage.pageSize
          };
          _this.$http.post({
            url: '/api/sdwan/tenant/getMultiDg',
            data: params
          }).then(res => {
            let { status, resultBody } = res;
            if (status === '0') {
              let { objects } = resultBody;
              let arry = [];
              for (let i = 0; i < objects.length; i++) {
                arry.push({
                  label: objects[i].userlabel,
                  value: objects[i].id
                });
              }
              _this.seloptions.push(...arry);
            }
          });
        });
      } else {
        // 空值时，触发重置
        this.seloptions = [];
        this.$nextTick(() => {
          _this.selPage = {
            page: 1,
            pageSize: 15,
            total: 0
          };
          let params = {
            limit: _this.selPage.pageSize,
            offset: (_this.selPage.page - 1) * _this.selPage.pageSize
          };
          _this.$http.post({
            url: '/api/sdwan/tenant/getMultiDg',
            data: params
          }).then(res => {
            let { status, resultBody } = res;
            if (status === '0') {
              let { objects } = resultBody;
              let arry = [];
              for (let i = 0; i < objects.length; i++) {
                arry.push({
                  label: objects[i].userlabel,
                  value: objects[i].id
                });
              }
              _this.seloptions.push(...arry);
            }
          });
        });
      }
    },
    // 显示DNS弹出框
    showDNS (data) {
      let _this = this;
      _this.dnsEdit = true;
      _this.dnsform.deviceId = data.deviceId;
      _this.dnsform.dnsIp = null;
    },
    // 更新DNS
    subDNS () {
      let _this = this;
      _this.$refs['dnsForm'].validate(valid => {
        if (valid) {
          let params = {
            deviceId: _this.dnsform.deviceId,
            dnsIp: _this.dnsform.dnsIp
          };
          this.$http.post({
            url: '/api/sdwan/vpn/server/updateDns',
            data: params
          }).then(result => {
            let { status } = result;
            if (status === '0') {
              _this.$message.success('设置成功！');
              _this.dnsEdit = false;
              _this.refresh();
            }
          });
        } else {
          _this.$message.error('请检查必填项！');
        }
      });
    },
    // 显示VPN Server弹出框
    showVPN (data) {
      let _this = this;
      // 根据租户ID查询 - 已关联
      _this.$http.post({
        url: '/api/sdwan/tenant/used/neList/byTenant',
        data: {
          dgId: data.dgId
        }
      }).then(res => {
        let { status, resultBody } = res;
        if (status === '0') {
          if (resultBody.length === 0) {
            _this.$message.error('无可用POP，请先配置骨干网编排！');
          } else {
            let arry = [];
            resultBody.map(item => {
              arry.push({
                value: item,
                label: item.userlabel
              });
            });
            _this.popls = arry;
            _this.vpnEdit = true;
            _this.vpnform.deviceId = data.deviceId;
            _this.vpnform.pop = null;
          }
        }
      });
    },
    // 提交VPN Server
    subVPN () {
      let _this = this;
      _this.$refs['vpnForm'].validate(valid => {
        if (valid) {
          let params = {
            deviceId: _this.vpnform.deviceId,
            pop: _this.vpnform.pop
          };
          this.$http.post({
            url: '/api/sdwan/vpn/server/connect',
            data: params
          }).then(result => {
            let { status } = result;
            if (status === '0') {
              _this.$message.success('设置成功！');
              _this.vpnEdit = false;
              _this.refresh();
            }
          });
        } else {
          _this.$message.error('请检查必填项！');
        }
      });
    },
    // 搜索
    search () {
      let _this = this;
      _this.page.page = 1;
      _this.refresh();
    },
    // 重置
    reset () {
      let _this = this;
      _this.page.page = 1;
      _this.filterSearch = {
        userName: null,
        dgId: null
      };
      _this.refresh();
    },
    // 刷新
    refresh () {
      let _this = this;
      let params = {
        userName: _this.filterSearch.userName,
        dgId: _this.filterSearch.dgId,
        limit: _this.page.pageSize,
        offset: (_this.page.page - 1) * _this.page.pageSize
      };
      _this.$http.post({
        url: '/api/sdwan/vpn/server/query',
        data: params
      }).then(res => {
        let { status, resultBody } = res;
        if (status === '0') {
          let { count, objects, offlineCount, onlineCount } = resultBody;
          _this.online = onlineCount;
          _this.offline = offlineCount;
          _this.page.total = count;
          _this.dataList = objects;
        }
      });
    },
    // 过滤显示字段
    changeColumn (columns) {
      this.columns = columns;
      this.$refs.table.doLayout();
    },
    // 切换页码 & 显示条数
    changePage (page) {
      if (page.page) {
        this.page.page = page.page;
      } else {
        this.page.page = 1;
        this.page.pageSize = page.limit;
      }
      this.refresh();
    },
    // 获取租户&角色
    getTenants () {
      let _this = this;
      let params = {
        hasDefault: false,
        limit: 0,
        offset: 0
      };
      _this.$http.post({
        url: '/api/sdwan/tenant/getMultiDg',
        data: params
      }).then(res => {
        let { status, resultBody } = res;
        if (status === '0') {
          let { objects } = resultBody;
          _this.tenantArry = objects;
        }
      });
    },
    // 显示弹出框
    showDialog (type, data) {
      let _this = this;
      _this.getTenants();
      _this.dvEdit = true;
      _this.dialogTitle = type === 'add' ? '新建' : '编辑';
      _this.$nextTick(() => {
        _this.$refs['ruleForm'].clearValidate();
      });
      if (type === 'add') {
        _this.form = {
          name: null,
          userName: null,
          licenseKey: null,
          deviceId: null,
          dgId: null
        };
      } else {
        _this.form = {
          id: data.row.id,
          name: data.row.name,
          userName: data.row.userName,
          licenseKey: data.row.licenseKey,
          deviceId: data.row.deviceId,
          dgId: data.row.dgId
        };
      }
    },
    // 提交
    onSubmit () {
      let _this = this;
      let params = {
        name: _this.form.name,
        userName: _this.form.userName,
        licenseKey: _this.form.licenseKey,
        deviceId: _this.form.deviceId,
        dgId: _this.form.dgId
      };
      _this.$refs['ruleForm'].validate(valid => {
        if (valid) {
          // 获取序列号
          this.$http.get({
            url: '/api/sdwan/vpn/server/token'
          }).then(res => {
            let { status, resultBody } = res;
            if (status === '0') {
              params.deviceId = resultBody;
              // 创建软终端
              _this.$http.post({
                url: '/api/sdwan/vpn/server/create',
                data: params
              }).then(result => {
                let { status } = result;
                if (status === '0') {
                  _this.$message.success('创建成功！');
                  _this.dvEdit = false;
                  _this.refresh();
                }
              });
            }
          });
        } else {
          _this.$message.error('请检查必填项！');
          return false;
        }
      });
    },
    // 删除
    handleDelete (scope) {
      let _this = this;
      this.$confirm('您确定要删除当前数据吗？', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'error'
      }).then(() => {
        _this.$http.deleted({
          url: '/api/sdwan/vpn/server/' + scope.row.id
        }).then(res => {
          let { status } = res;
          if (status === '0') {
            _this.$message.success('删除成功！');
            _this.refresh();
          }
        });
      }).catch(() => {
        _this.$message.info('取消删除');
      });
    },
    // 配置
    options (data) {
      let _this = this;
      // 判断软终端状态是否已登录
      _this.$http.get({
        url: '/api/sdwan/vpn/server/' + data.id
      }).then(res => {
        let { status, resultBody } = res;
        if (status === '0') {
          if (resultBody.status === 0) {
            _this.optionStatus = true;
            _this.introduce = resultBody;
          } else {
            this.$message.error('软终端状态异常！');
          }
        }
      });
    },
    // 回调
    handleChange (val) {
      let _this = this;
      _this.optionStatus = val;
      _this.reset();
    },
  }
};
</script>

<style lang='scss' scoped>
.page-content {
  width: 100%;
  height: 100%;

  .avatar {
    width: 50px;
    height: 50px;
    border-radius: 50%;
  }
  .table-box {
    ::v-deep .el-button {
      padding: 0;
    }
    ::v-deep .el-dropdown-link {
      cursor: pointer;
      color: #409eff;
      margin-left: 5px;
    }
  }

  ::v-deep .el-dialog__body {
    padding-bottom: 0;
  }
}
.on-off-box {
  float: left;
  margin-bottom: 15px;
}
.i-out {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: 8px;
  border-radius: 50%;
  background: #de4040;
  position: relative;
  top: 1px;
}
.i-login {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: 8px;
  border-radius: 50%;
  background: #67c23a;
  position: relative;
  top: 1px;
}
</style>